package com.seventhdawn.gwt.rpc.context.server;

import com.google.gwt.user.client.rpc.IsSerializable;
import com.seventhdawn.gwt.rpc.context.client.RPCClientContext;

/**
 * Server-side counterpart of {@link RPCClientContext}.
 * <p>
 * RPC service methods can use this class to access the deserialized context
 * object.
 * 
 * @see RPCClientContext
 * @see RPCContextFilter
 * @author vojtech.szocs
 */
public final class RPCServerContext {

    // deserialized RPC context object local to each thread on the server
    private static final ThreadLocal<IsSerializable> perThreadContextObject = new ThreadLocal<IsSerializable>();

    private RPCServerContext() {
    }

    /**
     * Returns the RPC context object that has been deserialized for the current
     * RPC call.
     * <p>
     * The context object itself is stored in a thread-local variable so that
     * multiple simultaneous threads have their own local copies.
     * <p>
     * Note that this method returns {@code null} when problems occur during RPC
     * context payload processing, such as:
     * <ul>
     * <li>{@link RPCContextFilter#IGNORE_MISSING_PAYLOAD missing RPC context
     * payload}
     * <li>{@link RPCContextFilter#IGNORE_SERIALIZATION_ERRORS context object
     * deserialization errors}
     * </ul>
     * 
     * @return RPC context object for the current RPC call or {@code null}.
     */
    public static IsSerializable get() {
        return perThreadContextObject.get();
    }

    /**
     * {@link RPCContextFilter} calls this method upon successful RPC context
     * object deserialization, prior to passing control to default RPC request
     * processing.
     * 
     * @param contextObject RPC context object to set for the current RPC call.
     */
    static void set(IsSerializable contextObject) {
        perThreadContextObject.set(contextObject);
    }

}
